﻿
/*******************************************************************
 综合实验1---Windows简易绘图器
 专业：21电子科学与技术
 姓名：李志坚
 学号：202100800413
********************************************************************/
#include <windows.h>
#include <windowsx.h>
#include "Resource.h"
#include "fileOperation.h"    //文件操作
#include "dataStruction.h"    //数据结构组织
#include "drawFunc.h"         //绘制功能


//回调函数声明
BOOL InitWindow(HINSTANCE hInstance, int nCmdShow);
LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);          //主窗口回调函数
BOOL CALLBACK SetTextContentProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);  //设置文本内容的对话框回调函数
BOOL CALLBACK FigureModifyProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);    //图形改变对话框处理回调函数
BOOL CALLBACK TextModifyProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);      //文本改变对话框的处理函数



//变量定义
#define MAX_TEXT_LEN   100
UINT gDrawMode;                              //当前绘画的图形
DATA_NODE* bufferFigureList = NULL;          //缓存链表
DATA_NODE selectedNode;                      //被选中的节点
CHAR  textEdit[MAX_TEXT_LEN];                //文本对话框的文本存储值

//主窗口回调函数
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)              
{
	MSG msg;
	char* p;

	//创建主窗口
	if (!InitWindow(hInstance, iCmdShow))
		return FALSE;

	p = 0;
	//进入消息循环：从该应用程序的消息队列中检取消息，
	//送到消息处理过程，当检取到WM_QUIT消息时，退出消息循环。
	while (GetMessage(&msg, NULL, 0, 0))
	{
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}

	return msg.wParam;
}

/******************************************************************
函数：InitWindow ()
功能：创建窗口。
*******************************************************************/
static BOOL InitWindow(HINSTANCE hInstance, int iCmdShow)
{
	static TCHAR szAppName[] = TEXT("comAPP1");  //应用程序名称
	HWND hwnd;                                    //窗口句柄
	WNDCLASS wcMainWnd;                           //窗口类结构
	ATOM a;

	//填充窗口类结构
	wcMainWnd.style = CS_VREDRAW | CS_HREDRAW;
	wcMainWnd.lpfnWndProc = WinProc;
	wcMainWnd.cbClsExtra = 0;
	wcMainWnd.cbWndExtra = 0;
	wcMainWnd.hInstance = hInstance;
	wcMainWnd.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));//替换图标
	wcMainWnd.hCursor = LoadCursor(NULL, IDC_ARROW);
	wcMainWnd.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wcMainWnd.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
	wcMainWnd.lpszClassName = szAppName;

	//注册窗口类
	a = RegisterClass(&wcMainWnd);

	if (!a)
	{
		MessageBox(NULL, TEXT("注册窗口类失败！"), szAppName,
			MB_ICONERROR);
		return 0;
	}

	//创建主窗口
	hwnd = CreateWindow(szAppName, 						//窗口类名称
		TEXT("综合实验1----简易绘图器（作者:山东大学（威海）warriorLi）"),  //窗口标题
		WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		CW_USEDEFAULT,
		NULL,
		NULL,
		hInstance,
		NULL);

	if (!hwnd) return FALSE;

	//显示并更新窗口
	ShowWindow(hwnd, iCmdShow);
	UpdateWindow(hwnd);
	return TRUE;
}

/******************************************************************
函数：WinProc ()
功能：处理主窗口消息
*******************************************************************/
LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	HDC         hdc;
	PAINTSTRUCT ps;
	RECT        rect;
	static POINT ptBegin, ptEnd;
	static POINT currentCur;

	switch (message)
	{
	case WM_CREATE:         //创建消息
		bufferFigureList = createDataList();  //创建缓冲区链表
		return 0;

	case WM_KEYDOWN:         //击键消息
		switch (wParam)
		{
		case VK_ESCAPE:
			MessageBox(hWnd, TEXT("ESC键按下了!"), TEXT("键盘"), MB_OK);
			break;
		}
		return 0;

	case WM_RBUTTONDOWN:        //鼠标消息
		//获取当前鼠标位置
		if (gDrawMode == DRAW_MODE_SELECT)
		{
			currentCur.x = GET_X_LPARAM(lParam);
			currentCur.y = GET_Y_LPARAM(lParam);

			//如果有选中的东西
			if (SelectNodeFromList(bufferFigureList, currentCur, &selectedNode) == TRUE)
			{
				//MessageBox(hWnd, TEXT("鼠标右键按下了!"), TEXT("鼠标"), MB_OK);
				if (selectedNode.Figure == F_TEXT)    //文本图元
				{
					if (DialogBox((HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), MAKEINTRESOURCE(IDD_DIALOG_TEXTMODIFY), hWnd, TextModifyProc) == TRUE)
					{
						fileChangeFlag++;                   //有修改或删除，改动标志位自增
						InvalidateRect(hWnd, NULL, TRUE);   //更新显示
					}
				}
				else   //图形
				{
					if (DialogBox((HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), MAKEINTRESOURCE(IDD_DIALOG_FIGURE_MODIFY), hWnd, FigureModifyProc) == TRUE)
					{
						fileChangeFlag++;                   //有修改或删除，改动标志位自增
						InvalidateRect(hWnd, NULL, TRUE);   //更新显示
					}
				}
				
			}
			
		}
		
		return 0;


	case WM_LBUTTONDOWN:
		if (gDrawMode != DRAW_MODE_SELECT)
		{
			bDrawing = TRUE;

			SetCapture(hWnd);
			ptBegin.x = GET_X_LPARAM(lParam);
			ptBegin.y = GET_Y_LPARAM(lParam);
		}

		return 0;


	case WM_LBUTTONUP:
		if (bDrawing)
		{
			BOOL bNew = FALSE;
			ptEnd.x = GET_X_LPARAM(lParam);
			ptEnd.y = GET_Y_LPARAM(lParam);
			if (gDrawMode == DRAW_MODE_LINE)                                    //添加一个线到缓冲区中
				bNew = AddOneLineToList(ptBegin, ptEnd, bufferFigureList);   
			if (gDrawMode == DRAW_MODE_RECT)                                    //添加一个矩形到缓冲区
				bNew = AddOneRectToList(ptBegin, ptEnd, bufferFigureList);
			if (gDrawMode == DRAW_MODE_ELLIPSE)                                 //添加一个椭圆到缓冲区
				bNew = AddOneEllipseToList(ptBegin, ptEnd, bufferFigureList);
			if (gDrawMode == DRAW_MODE_TEXT)                                    //添加一个矩形到缓冲区
			{
				//调用对话框获取文本
				if (DialogBox((HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE), MAKEINTRESOURCE(IDD_DIALOG_TEXT), hWnd, SetTextContentProc) == TRUE)
				{
					bNew = AddOneTextToList(ptBegin, ptEnd,textEdit,bufferFigureList);
				}
			}
		    //更新界面
			if (bNew)
				InvalidateRect(hWnd, NULL, TRUE);
			ReleaseCapture();
		}
		return 0;


	case WM_COMMAND:
		if (lParam) //lParam == 1控件或子窗口命令
		{

		}
		else      //lParam == 0菜单命令
		{
			switch (LOWORD(wParam))
			{
			case ID_M_OPEN:
				//通过文件通用对话框获取文件名，打开，读出图形数据
				if (openFileReadFigureData(hWnd) == TRUE)
				{
					fileChangeFlag = 0;
					InvalidateRect(hWnd, NULL, TRUE);
				}
					
				break;
            
			case ID_M_SAVEOTHER:
				//把图形数据保存到文件
				if (openFileSaveFigureData(hWnd))       //另存为
				{
					fileChangeFlag = 0;                 //文件改动标记清零
					fileOpenFlag = YES;                 //文件打开
				}
				break;

			case ID_M_SAVE:
				if (fileOpenFlag == NO)
				{
					if (openFileSaveFigureData(hWnd))       //另存为
					{
						fileChangeFlag = 0;                 //文件改动标记清零
						fileOpenFlag = YES;                 //文件打开
					}
				}
				else
				{
					if (saveFigureDataToCurrentFile(hWnd))  //保存
					{
						fileChangeFlag = 0;                 //文件改动标记清零
						fileOpenFlag = YES;                 //文件打开
					}
				}
				InvalidateRect(hWnd, NULL, TRUE);
				break;

			case ID_M_CLOSE:
				fileOpenFlag = NO;
				memset(currentFileName,'\0',sizeof(currentFileName));
			    memset(currentFileTitle, '\0', sizeof(currentFileTitle));
				clearBufferList(bufferFigureList);
				InvalidateRect(hWnd, NULL, TRUE);
				break;

			case ID_SELECT_FONT:
				DrawChooseFont(hWnd,&(gLogFont),&(gColorText));
				break;

			case ID_FILL_COLOR:
				SelectColor(hWnd, &(gbrushColor));
				break;

			case ID_DRAW_LINECOLOR:
				SelectColor(hWnd, &(gpenColor));
				break;

			case ID_FIGURE_SELECT:  gDrawMode = DRAW_MODE_SELECT;                  break;
			case ID_FIGURE_LINE:    gDrawMode = DRAW_MODE_LINE;                    break;
			case ID_FIGURE_RECT:    gDrawMode = DRAW_MODE_RECT;					   break;
			case ID_FIGURE_ELLIPSE:    gDrawMode = DRAW_MODE_ELLIPSE;              break;
			case ID_FIGURE_TEXT:    gDrawMode = DRAW_MODE_TEXT;                    break;

			case ID_MENU_SHOWHELP:  
				MessageBox(hWnd, TEXT("欢迎您使用简易绘图器V1.0,本绘图器完整完成了山东大学(威海)《面向对象编程》的全部要求。该工程可以用于链表结构的学习和Windows SDK开发，在课程结束后，源码会开源至Gitee：https://gitee.com/warrior_Li 欢迎大家一起交流学习！"), TEXT("帮助"), MB_OK);
				break;
			}
		}
	return 0;

	case WM_PAINT:              //客户区重绘消息

		//取得设备环境句柄
		hdc = BeginPaint(hWnd, &ps);

		//取得窗口客户区矩形
		GetClientRect(hWnd, &rect);
		//显示所有图形
		drawALLFigure(bufferFigureList,hdc);
		//显示当前文件名称
		if (fileOpenFlag == YES)     //文本打开
		{
			showFileStateOnRightBottom(hdc,rect);
		}
		//释放资源
		EndPaint(hWnd, &ps);
		return 0;


	case WM_INITMENUPOPUP:       //设置菜单显示状态
		if (LOWORD(lParam) == 1)
		{
			CheckMenuItem((HMENU)wParam, ID_FIGURE_SELECT, gDrawMode == DRAW_MODE_SELECT ? MF_CHECKED : MF_UNCHECKED);
			CheckMenuItem((HMENU)wParam, ID_FIGURE_LINE, gDrawMode == DRAW_MODE_LINE ? MF_CHECKED : MF_UNCHECKED);
			CheckMenuItem((HMENU)wParam, ID_FIGURE_RECT, gDrawMode == DRAW_MODE_RECT ? MF_CHECKED : MF_UNCHECKED);
			CheckMenuItem((HMENU)wParam, ID_FIGURE_ELLIPSE, gDrawMode == DRAW_MODE_ELLIPSE ? MF_CHECKED : MF_UNCHECKED);
			CheckMenuItem((HMENU)wParam, ID_FIGURE_TEXT, gDrawMode == DRAW_MODE_TEXT ? MF_CHECKED : MF_UNCHECKED);
		}
		return 0;

	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;

	}

	//调用缺省消息处理过程
	return DefWindowProc(hWnd, message, wParam, lParam);

} //函数 WinProc 结束


//文本输入对话框回调处理回调函数
BOOL CALLBACK SetTextContentProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{

	switch (message)
	{
	case WM_INITDIALOG:
		return FALSE;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case ID_DIA_OK:              //确认按钮
			memset(textEdit,0,sizeof(textEdit));
			GetDlgItemText(hDlg, IDC_D_TEXT_EDIT, textEdit, MAX_TEXT_LEN);  //收取文本框中的文本值
			EndDialog(hDlg, TRUE);
			return TRUE;

		case ID_DIA_CANCEL:          //取消按钮
			EndDialog(hDlg, FALSE);
			return FALSE;
		}
		break;
	
	case WM_CLOSE:
		EndDialog(hDlg, FALSE);
		return FALSE;
	
	}
	return FALSE;

}//结束 SeSetTextContentProc


//图形改变对话框处理回调函数
BOOL CALLBACK FigureModifyProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	HWND hComboBox;
	char tempString[50] = { '\0'};
	BYTE R1, G1, B1;
	int comboBox_index = 0;

	switch (message)
	{
	case WM_INITDIALOG:
		//初始化控件
	    hComboBox = GetDlgItem(hDlg, IDC_D_COM_LINETYPE);
		//填充ComboBox选项
		SendMessage(hComboBox, CB_ADDSTRING, 1, (LPARAM)TEXT("实线"));    //1是实线
		SendMessage(hComboBox, CB_ADDSTRING, 2, (LPARAM)TEXT("虚线"));    //2是虚线
		SendMessage(hComboBox, CB_ADDSTRING, 3, (LPARAM)TEXT("点"));      //3是点
		showSelectNodeInformation(hDlg, selectedNode);

		return FALSE;

	case WM_COMMAND:
		//combo Box控件消息
		if (HIWORD(wParam) == CBN_SELENDOK)//用户已经完成了选择并且下拉框已经关闭
		{
			hComboBox = GetDlgItem(hDlg, IDC_D_COM_LINETYPE);
			comboBox_index = SendMessage(hComboBox, CB_GETCURSEL, 0, 0);
			switch (comboBox_index)
			{
			case 1:
				changedLineType = PS_SOLID;  //实现
				break;
			case 2:
				changedLineType = PS_DASH;  //虚线
				break;
			case 0:
				changedLineType = PS_DOT; //点
				break;
			}
		}

		switch (LOWORD(wParam))
		{
		case ID_BUTTON_SELECTLINECOLOR:   //修改颜色的按钮
			if (SelectColor(hDlg, &(changedLineColor)))
			{
				R1 = GetRValue(changedLineColor);
				G1 = GetGValue(changedLineColor);
				B1 = GetBValue(changedLineColor);
				wsprintf(tempString, "RGB(%d,%d,%d)", R1, G1, B1);
				SetDlgItemText(hDlg, IDC_EDIT_FIGURE_LINECOLOR, tempString);
			}
			return FALSE;
		
		case ID_BUTTON_SELECTFILLCOLOR:   //修改填充色的按钮
			if (SelectColor(hDlg, &(changedFillColor)))
			{
				R1 = GetRValue(changedFillColor);
				G1 = GetGValue(changedFillColor);
				B1 = GetBValue(changedFillColor);
				wsprintf(tempString, "RGB(%d,%d,%d)", R1, G1, B1);
				SetDlgItemText(hDlg, IDC_EDIT_FIGURE_FILLCOLOR, tempString);
			}
			return FALSE;


		case ID_DELETE:
			deleteSelectedNodeFromList(bufferFigureList);     
			clearSelectedFlag(bufferFigureList);              //清空选择标志位
			EndDialog(hDlg, TRUE);
			return TRUE;

		case ID_MODIFY:
			getModifyInformationFormDLg(hDlg, &selectedNode);
			modifySelectNodeFromList(bufferFigureList, selectedNode);
			clearSelectedFlag(bufferFigureList);      //清空选择标志位
			EndDialog(hDlg, TRUE);
			return TRUE;


		case ID_CANCEL:               //取消按钮
			clearSelectedFlag(bufferFigureList);      //清空链表中的选择标志位
			EndDialog(hDlg, FALSE);
			return FALSE;
		}
		break;
	
	case WM_CLOSE:
		EndDialog(hDlg, FALSE);
		return FALSE;
	}
	return FALSE;

}//结束 FigureModifyProc


//文本改变对话框处理回调函数
BOOL CALLBACK TextModifyProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
	switch (message)
	{
	case WM_INITDIALOG:
		showSelectNodeInformation(hDlg, selectedNode);
		return FALSE;

	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDC_CHANGE_FONT:   //修改颜色的按钮
			DrawChooseFont(hDlg, &(changedLogFont), &(changedColorText));
			return FALSE;

		case ID_TEXTMODIFY_DELETE:
			deleteSelectedNodeFromList(bufferFigureList);
			clearSelectedFlag(bufferFigureList);      //清空选择标志位
			EndDialog(hDlg, TRUE);
			return TRUE;

		case ID_TEXTMODIFY_MODIFY:
			getModifyInformationFormDLg(hDlg, &selectedNode);
			modifySelectNodeFromList(bufferFigureList, selectedNode);
			clearSelectedFlag(bufferFigureList);      //清空选择标志位
			EndDialog(hDlg, TRUE);
			return TRUE;


		case IDCANCEL:                                //取消按钮
			clearSelectedFlag(bufferFigureList);      //清空链表中的选择标志位
			EndDialog(hDlg, FALSE);
			return FALSE;

		}
		break;

	case WM_CLOSE:
		EndDialog(hDlg, FALSE);
		return FALSE;
	}
	return FALSE;

}//结束 TextModifyProc